<?php
/**
 * 最简单的排行榜
 *  1.可以实现增加或者重置
 *  2.可以设置有效期
 *  3.获取榜单
 *  4.获取用户对应的排名和积分
 *
 */
class Rank
{
    public $key =  null;
    public $expire = null;
    public $redis = null;
    public $isSetTtl = false;

    function __construct($data) {
        $this->redis = new Redis();
        foreach($data as $k => $v) {
            $this->$k = $v;
        }
    }

    /**
     * 设置分数
     */
    function set($member,$score, $incr = false)
    {
        $key = $this->key;
        $redis = $this->redis;
        $expire = $this->expire;
        //自增
        if ($incr) {
            $ret = $redis->zIncrBy($key ,$score, $member);
        } else {
            $ret = $redis->zAdd($key,$score, $member);
        }
        if ($expire && !$this->isSetTtl) {
            if (-1 === $redis->ttl($key)) {
                $redis->expire($key, $expire);
                $this->isSetTtl = true;
            }
        }
        return $ret;
    }

    /**
     * 自增分数
     */
    function incr($member,$score)
    {
        $ret = $this->set($member, $score, true);
        return $ret;
    }


    /**
     * 获取排行榜列表 降序排行
     */
    function getRankList($count = 100)
    {
        $key = $this->key;
        $redis = $this->redis;
        $list = $redis->zRevRange($key,0, $count-1, true);
        return $list;
    }

    /**
     * 获取用户的排行榜信息
     */
    function getInfo($member)
    {
        $key = $this->key;
        $redis = $this->redis;
        $data['score'] = $redis->zScore($key, $member);
        $data['rank'] = $redis->zRevRank($key, $member);
        return $data;
    }

    /**
     * 统计排行榜人数
     * $star = 1 过滤小与等于0的人
     */
    function count($star = '-inf', $end = '+inf')
    {
        $key = $this->key;
        $redis = $this->redis;
        $count = $redis->zCount($key, $star, $end);
        return $count;
    }


    /**
     * 生成测试排行榜
     */
    function generate($num = 100, $shuffle = true, $step = 1, $init = 1)
    {
        $key = $this->key;
        $redis = $this->redis;
        $expire = $this->expire;
        $arr = range('a', 'z');
        $score = $init-$step;
        for($i = 1;$i< $num;$i++) {
            // $redis->zAdd($key, rand(200,300), $i);
            $member = $arr[rand(0,25)] . $i;
            $score = $shuffle ?  rand(200,300) : $score + $step;
            $this->set($member, $score);
        }
        $redis->expire($key, $expire);
    }

    /**
     * 生成测试排行榜
     */
    function simGen($num = 100)
    {
        $key = $this->key;
        $redis = $this->redis;
        $expire = $this->expire;
        for($i = 1;$i< $num;$i++) {
            $redis->zAdd($key, rand(200,300), $i);
        }
        $redis->expire($key, $expire);
    }
}